//---------------------------------------------------------------------
// ianime.js - Animation module for iPhone and iPod touch
//   version 0.26 (Dec. 3rd, 2007)
//
// [Usage]
// 1. The MIT License (see below)
// 2. Feedback is welcome at
//   http://satoshi.blogs.com/uie/2007/11/ianime_js.html
// 
// [MIT License]
//
// Copyright (c) 2007-2008 Satoshi Nakajima
//  
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//---------------------------------------------------------------------

var iAnime = function() {
    this.items = new Array();
};

iAnime.effects = new Array();

iAnime.drawElement = function(e,r,x,y) {
    e.style.left = x + "px";
    e.style.top = y + "px";
};

iAnime.poly = function(n) {
    if (iAnime.poly[n]) {
        return iAnime.poly[n];
    }
    var poly = [];
    var p = n+1;
    for (var i=0; i<n; i++) {
        p *= (i+1);
    }
    var l = p;
    var r = 1;
    for (var i=0; i<n; i++) {
        l = l/(n+1-i);
        r = r*(i+1);
        poly[i] = p/l/r;
    }
    // cache it
    iAnime.poly[n] = poly;
    return poly;
};

// pre-cached for common cases
iAnime.poly[1] = [2];
iAnime.poly[2] = [3,3];
iAnime.poly[3] = [4,6,4];

iAnime.prototype = {
    citems: 0, timer: 0, frames: 0,
    paused: false,
    // Default parameters (can be overridden)
    delay: 33
};

iAnime.noop = function() {};

iAnime.prototype.add = function(param)
{
    if (!param.duration) param.duration=1;
    if (param.id) {
        param.element = document.getElementById(param.id);
    }
    if (param.element) {
        param._sx = param.element.offsetLeft;
        param._sy = param.element.offsetTop;
    }
    if (!param.x) param.x = param._sx;
    if (!param.y) param.y = param._sy;
    param._dx = param.x - param._sx;
    param._dy = param.y - param._sy;   
    param.st = this.paused ? this.pTime : (1*(new Date));
    if (param.effect && iAnime.effects[param.effect]) {
        param.drawElement = iAnime.effects[param.effect];
        if (param.drawElement.init) {
            param.drawElement.init(param);
        }
    } else {
        param.drawElement = param.element ? iAnime.drawElement : iAnime.noop;
    }
    // Process Besier control points, if any 
    if (param.cp) {
        var poly = iAnime.poly(param.cp.length);
        param._cx = [];
        param._cy = [];
        for (var i=0; i<param.cp.length; i++) {
            param._cx[i] = poly[i] * (param.cp[i].x-param._sx);
            param._cy[i] = poly[i] * (param.cp[i].y-param._sy);
        }
    }
    this.items[this.citems++] = param;
    param.drawElement(param.element, 0, param._sx, param._sy);
    if (this.paused==false) {
        if (this.timer==0) {
            this.frames=0;
            var self = this;
            this.timer = setInterval(function() {self.tick();}, this.delay);
        }
    }
    return param;
};

iAnime.prototype.addSequence = function(seq)
{
    if (seq.length==0) return;
    var item = seq.shift();
    if (item[0]) {
        // Nested sequence
        this.addSequence(item);
        this.addSequence(seq);
    } else {
        var self = this;
        var prev = item.onComplete;
        item.onComplete = function() { 
            if (prev) prev(item);
            self.addSequence(seq);
        } 
        this.add(item);
    }
}

iAnime.prototype.pause = function(pause)
{
  if (pause) {
    if (!this.paused) {
      if (this.timer) {
        clearInterval(this.timer);
        this.timer = 0;
      }
      this.pTime = 1*(new Date);
    }
  } else {
    if (this.paused && this.citems>0) {
      var duration = 1*(new Date) - this.pTime;
      for (var i=this.citems-1; i>=0; i--) {
        this.items[i].st += duration;
      }
      this.frames = 0;
      var self = this;
      this.timer = setInterval(function() {self.tick();}, this.delay);
    }
  }
  this.paused = pause;      
}

iAnime.prototype.tick = function()
{
    this.frames++;
    var now = 1*(new Date);
    for (var i = this.citems - 1 ; i >= 0 ; i--) {
        var item = this.items[i];
        var t = (now - item.st) / item.duration;
        if (t < 1) {
            if (item.drawElement.ratio) {
                t = item.drawElement.ratio(t);
            }
            if (item._cx) {
                var t1 = (1-t);
                var p = t;
                for (var j=0; j<item._cx.length; j++) {
                    p *= t1;
                }               
                var x = item._sx;
                var y = item._sy;
                for (var j=0; j<item._cx.length; j++) {
                    x += p * item._cx[j];
                    y += p * item._cy[j];
                    p = p/t1*t;
                }
                x += p*item._dx;
                y += p*item._dy;
                item.drawElement(item.element, t, x, y);
            } else {
                item.drawElement(item.element, t,
                    item._sx+item._dx*t, item._sy+item._dy*t);
            }
        } else {
            item.drawElement(item.element, 1,
                item._sx+item._dx, item._sy+item._dy);
            this.items[i] = this.items[--this.citems];
            this.items[this.citems] = null;
            if (item.onComplete) {
                item.onComplete();
            }
        }
    }
    // Stop the timer if there is no animation
    if (this.citems==0) {
        clearInterval(this.timer);
        this.timer = 0;
    }
};

